import Pubsub from 'pubsub-js'
import moment from 'moment'
Page({
  data: {
    isPlay: true, // 默认歌曲是播放的
    songId: '', // 用来存储当前播放的歌曲id
    songDetail: {}, // 存储歌曲的详细信息
    songUrl: '', // 存储歌曲的播放地址
    player: null, // 存储歌曲播放实例
    w: '', // 进度条的已完成进度的宽度
    startTime: '', // 歌曲起始时间
    endTime: '', // 歌曲的结束时间
  },
  /**
   * 写页面的步骤:
   * 1. 静态搭建
   *    写出整个歌曲播放页面的静态
   *    注意: 给页面设置 宽高100% css的时候不好使,如何解决?
   *          在全局css(app.wxss文件)设置 page { width: 100%; height: 100% }
   * 2. 初始化数据展示
   *    2.1 展示歌曲的信息(发请求)
   *        拿到歌曲信息的时候,需要存储到 数据中,在页面展示,需要的数据有: 作者名、歌曲名、封面图
   *    2.2 播放歌曲(发请求)
   * 3. 交互
   *    3.1 创建播放实例 - 给播放实例设置src和title即可[自动播放](自动播放默认就是播放状态)
   *        在自动播放的状态下,我们需要一个值记录播放状态
   *        isPlay 参数记录播放状态
   *    3.2
   *        3.2.1 播放状态下页面展示的效果
   *              1. 唱针放在唱片上
   *              2. 唱片应该转动
   *              3. 控制区域"播放/暂停按钮"的显示
   *              4. 歌曲的播放(先做这步)
   *        3.2.2 暂停状态下页面展示的效果
   *              1. 唱针不在唱片上
   *              2. 唱片应该停止滚动
   *              3. 控制区域"播放/暂停按钮"的显示
   *              4. 歌曲的暂停(先做这步)
   *    3.3 暂停/播放
   *        3.3.1 点击页面控制区域,"暂停/播放"按钮,要对歌曲进行暂停和播放(先做这步)
   *        3.3.2 点击系统的播放暂停,也需要修改 isPlay 的状态
   *              真机测试的时候,看不到模拟器下方的控制区域,但是小程序后台是可以控制音乐的播放和暂停的
   *    3.4 下一首/上一首
   *        当点击"下一首/上一首"的时候,需要切换歌曲的播放
   *        3.4.1 给"下一首/上一首"按钮绑定点击事件
   *              在事件回调中拿到点击的是"上一首"还是"下一首",通过给标签绑定自定义属性进行区分
   *        3.4.2 需要去之前的 歌曲列表 页面,拿到当前歌曲的"上一首"/"下一首"
   *              这里涉及到一个问题,两个页面之间的通信(歌曲播放页面和歌曲列表页面)
   *              这里使用pubsub进行通信
   *              在小程序中如何使用 pubsub(第三方插件)?
   *              1. 创建 package.json
   *                  在项目目录终端,使用 `npm  init` 指令初始化一个 package.json 文件
   *              2. 安装第三方包
   *                  npm i pubsub-js
   *              3. 点击小程序IDE "工具 -> 构建npm" 选项
   *                  将安装的依赖让小程序的编辑器可以找到
   *              使用pubsub的步骤:
   *              1. 安装引入
   *              2. 在接收参数的页面,绑定事件(订阅消息),留下回调,接收参数
   *              3. 在发送参数的页面,触发事件(发送消息),传递参数
   *        3.4.3
   *              在歌曲列表页接收到歌曲播放页传过来的数据的时候,找到当前的歌曲
   *              再去找上一首/下一首
   *              找到之后,需要再次传递给歌曲播放页面
   *        3.4.4
   *              通过pubsub,新的歌曲ID(上一首/下一首的id)再次传递给 歌曲播放页即可
   *
   *        3.4.5
   *              点击上一首/下一首的时候,需要考虑边界条件
   *              当播放的是第一首的时候,点击上一首,此时应该跳转到最后一首播放
   *              当播放的是最后一首的时候,点击下一首,此时应该跳转到第一首播放
   *              这个判断条件应该加在上一首下一首 index 切换的位置
   *        3.4.6
   *              当播放歌曲完毕的时候,自动切换至下一首
   *              需要给当前player实例,绑定一个播放完毕的回调,当播放完毕的时候,触发回调,切换下一首
   *              在创建 player 实例的时候,绑定回调
   *    3.5 关于进度条最后说
   *        进度条这里只做展示
   *        3.5.1 先画静态
   *            静态中,红色的线代表已完成(已播放)的进度,放到白色的线当中即可
   *            小圆点控制放在红色的线最右侧即可,永远放在这个位置,只需要控制红色线宽度就可以控制小圆点的位置
   *        3.5.2 然后根据时间实时的展示当前进度条的位置
   *            实时需要设置的有 起始时间,结束时间,已完成进度条的宽度(红色的线宽)
   *            需要播放实例有一个实时的播放回调,在创建播放实例的时候,绑定上回调即可
   *            问题: player实例实时播放的回调中,可以通过实例拿到 已完成时间 和 总时长
   *            根据 已完成时间 和 总时长 可以算出已完成进度条的宽度(红色进度条的宽度)
   *            但是已完成时间 和 总时长单位是秒,需要转成标准格式,怎么转?
   *            解答:
   *            使用第三方包 moment.js 来转
   *            1. 安装
   *                在终端里面执行 `npm i moment`
   *            2. 安装好之后要 "工具" -> "构建npm" 执行, 每当我们新安装了第三方包的时候,就需要重新构建
   *            
   */           
  // 切换上一首,下一首的回调
  changeSong(e) {
    const operate = e.currentTarget.dataset.operate; // 'prev' 'next'
    // 需要把当前歌曲的id 和 操作传给 歌曲列表页
    Pubsub.publish('currentSongId', {
      operate, // 'prev' 和 'next'
      songId: this.data.songId // 传递歌曲id为了让歌曲列表页,找到当前播放的是哪一首
    })
  },
  // 切换播放状态
  changePlay() {
    if (this.data.isPlay) { // true 代表播放中,此时应该暂停
      this.data.player.pause(); // 拿到实例之后调用暂停方法
    } else { // false 代表暂停中,此时应该播放
      this.data.player.play() // 拿到实例之后调用播放方法
    }
    // 同时修改播放状态
    this.setData({
      isPlay: !this.data.isPlay // 状态取反即可
    })
  },
  // 获取歌曲的详细信息
  async getSongDetail() {
    try {
      let result = await this.$myAxios(`/song/detail`, { ids: this.data.songId });
      this.setData({
        songDetail: {
          id: this.data.songId,
          songName: result.songs[0].al.name, // 歌曲名
          coverImg: result.songs[0].al.picUrl, // 封面图
          authorName: result.songs[0].ar[0].name // 作者名
        }
      })
      // 页面中要展示数据
      wx.setNavigationBarTitle({
        title: result.songs[0].al.name,
      })
    } catch (error) {
      console.error('获取歌曲详细信息失败')
    }
  },
  // 获取歌曲的url
  async getSongUrl() {
    try {
      let result = await this.$myAxios(`/song/url`, { id: this.data.songId })
      this.setData({
        songUrl: result.data[0].url
      })
    } catch (error) {
      console.error('获取歌曲的播放地址失败')
      // 注意: 有些歌曲是获取到地址,接口的问题,不是我们的问题,绝大多数歌曲可以获取到播放地址
    }
  },
  // 创建播放实例
  createSongManager() {
    if (!this.data.player) { // 保证页面中只有这一个播放实例
      this.setData({
        player: wx.getBackgroundAudioManager()
      })
    }
    this.data.player.src = this.data.songUrl; // 给播放实例设置播放地址
    this.data.player.title = this.data.songDetail.songName; // 给播放实例设置标题
    this.data.player.onPlay(() => { // 播放的回调
      this.setData({
        isPlay: true
      })
    })
    this.data.player.onPause(() => { // 暂停的回调
      this.setData({
        isPlay: false
      })
    })
    this.data.player.onEnded(() => { // 自然播放完毕的回调
      // 切换下一首
      Pubsub.publish('currentSongId', {
        operate: 'next',
        songId: this.data.songId 
      })
    })
    this.data.player.onTimeUpdate(() => {
      // this.data.player.currentTime // 当前播放的时长,单位是秒
      // this.data.player.duration // 总时长,单位是秒
      // 已完成宽度 = 进度条总宽度 * 已完成的比例(已完成的时间/总时长)
      let w = 400 * this.data.player.currentTime / this.data.player.duration

      // moment插件的单位是毫秒,我们实例数据中 this.data.player.currentTime 单位是秒
      let startTime = moment(this.data.player.currentTime * 1000).format('mm:ss')
      let endTime = moment(this.data.player.duration * 1000).format('mm:ss')

      this.setData({
        startTime,
        endTime,
        w
      })
    })
  },
  onLoad: async function (options) {
    // console.log('options',options)
    const { songId } = options;

    this.setData({
      songId
    })

    // 获取歌曲的信息
    await this.getSongDetail();
    // 获取歌曲播放的url
    await this.getSongUrl();
    // 播放歌曲 - 创建播放实例
    this.createSongManager()

    // 绑定上一首下一首的歌曲传递id事件
    Pubsub.subscribe('newSongId', async (messageType, data) => {
      const songId = data.newSongId; // 拿到新的歌曲id

      this.setData({
        songId
      })
  
      // 获取歌曲的信息
      await this.getSongDetail();
      // 获取歌曲播放的url
      await this.getSongUrl();
      // 播放歌曲 - 创建播放实例
      this.createSongManager()
    })


    // 1. query传参
    // const {songId} = options;
    // console.log(songId)
    // 2. storage
    // const songId = wx.getStorageSync('songId')
    // console.log(songId)
    // 3. app 实例传参
    // const app = getApp();
    // console.log('app传参', app.songId)
    // 4. 事件通道
    // const eventChannel = this.getOpenerEventChannel();
    // eventChannel.on('sendSongId', (data) => {
    //   console.log('事件通道回调参数', data)
    // })
  },
  // 通过onShow做的页面访问权限,所以这个钩子必须保留,否则会报错
  onShow: function () {}
})